<!doctype html>
<head>
    <title>Threebox raycaster of Objects3D, 3D models and Fill-extrusions</title>
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css" rel="stylesheet" />
    <script src="../dist/threebox.js" type="text/javascript"></script>
    <link href="../dist/threebox.css" rel="stylesheet" />
    <script src="config.js"></script>
    <style>
        body, html {
            width: 100%;
            height: 100%;
            margin: 0;
        }

        #map {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <div id='map' class='map'></div>

    <script type="module">
        if (!config) console.error("Config not set! Make a copy of 'config_template.js', add in your access token, and save the file as 'config.js'.");

		mapboxgl.accessToken = config.accessToken;
        let origin1 = [-122.3512, 47.6202, 0];
		let origin2 = [-122.34548, 47.617538, 0];
        let origin3 = [-122.3491, 47.6207, 0];

        let minZoom = 12;
        let names = {
            compositeSource: "composite",
            compositeSourceLayer: "building",
            compositeLayer: "3d-buildings"

        }
        var map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/outdoors-v11',
            center: origin3,
            zoom: 16.5,
            pitch: 60,
            heading: 0, hash: true
        });

        // we can add Threebox to mapbox to add built-in mouseover/mouseout and click behaviors
        window.tb = new Threebox(
            map,
            map.getCanvas().getContext('webgl'),
            {
                defaultLights: true,
                enableSelectingFeatures: true, //change this to false to disable fill-extrusion features selection
                enableSelectingObjects: true, //change this to false to disable 3D objects selection
                enableDraggingObjects: true, //change this to false to disable 3D objects drag & move once selected
                enableRotatingObjects: true, //change this to false to disable 3D objects rotation once selected
                enableTooltips: true, // change this to false to disable default tooltips on fill-extrusion and 3D models
            }
        );

        var redMaterial = new THREE.MeshPhongMaterial({
            color: 0x660000,
            side: THREE.DoubleSide
        });

		import { GUI } from 'https://threejs.org/examples/jsm/libs/dat.gui.module.js';
		import Stats from 'https://threejs.org/examples/jsm/libs/stats.module.js';

		let stats, gui;
		function animate() {
			requestAnimationFrame(animate);
			stats.update();
		}

		var active = false
		map.on('style.load', function () {
			init();

            map.addLayer(createCompositeLayer());

            map.addLayer({
                id: 'custom_layer',
                type: 'custom',
                renderingMode: '3d',
                onAdd: function (map, mbxContext) {

                    tb.altitudeStep = 1;

                    //// initialize geometry and material of our cube object
                    var geometry = new THREE.BoxGeometry(30, 60, 120);

                    //[jscastro] we add a cube with no bbox and despite is raycasted
                    let cube = new THREE.Mesh(geometry, redMaterial);
                    cube = tb.Object3D({ obj: cube, units: 'meters', bbox: false})
                        .setCoords(origin1);
					cube.addTooltip("This object is selectable but without bounding box", true);
                    tb.add(cube);

                    //[jscastro] we add a sphere
                    let sphere = tb.sphere(
                        {
                            radius: 30,
                            units: 'meters',
                            sides: 120,
                            color: 'green',
                            material: 'MeshPhysicalMaterial',
                        }
                    ).setCoords(origin2);
                    tb.add(sphere);

                    // import soldier from an external glb file, scaling up its size 20x
                    // IMPORTANT: .glb is not a standard MIME TYPE, you'll have to add it to your web server config,
                    // otherwise you'll receive a 404 error

                    // Attribution: Soldier animated model by T. Choonyung at https://www.mixamo.com
					// from https://www.mixamo.com/#/?page=1&query=vanguard&type=Character
                    var options = {
                        obj: './models/soldier.glb',
                        type: 'gltf',
                        scale: 100,
                        units: 'meters',
                        rotation: { x: 90, y: 0, z: 0 }, //default rotation
                        anchor: 'center'
                    }

                    tb.loadObj(options, function (model) {
                        //origin3[2] += model.modelSize.z;
                        let soldier = model.setCoords(origin3);
						model.addLabel(createLabelIcon("Status: Radioactive"), true); //+ '&#013;' + feature.properties.name
						model.addTooltip("This is a custom tooltip", true);

                        tb.add(soldier);
                        // play animation 3, for 10 seconds
                        soldier.playAnimation(options = { animation: 1, duration: 10000 });

                    })

                },

                render: function (gl, matrix) {
                    tb.update();
                }
            });

        });

        function createCompositeLayer() {
            let layer = {
                'id': names.compositeLayer,
                'source': names.compositeSource,
                'source-layer': names.compositeSourceLayer,
                'filter': ['==', 'extrude', 'true'],
                'type': 'fill-extrusion',
                'minzoom': minZoom,
                'paint': {
                    'fill-extrusion-color':
                        [
                            'case',
                            ['boolean', ['feature-state', 'select'], false],
                            "lightgreen",
                            ['boolean', ['feature-state', 'hover'], false],
                            "lightblue",
                            '#aaa'
                        ],

                    // use an 'interpolate' expression to add a smooth transition effect to the
                    // buildings as the user zooms in
                    'fill-extrusion-height': [
                        'interpolate',
                        ['linear'],
                        ['zoom'],
                        minZoom,
                        0,
                        minZoom + 0.05,
                        ['get', 'height']
                    ],
                    'fill-extrusion-base': [
                        'interpolate',
                        ['linear'],
                        ['zoom'],
                        minZoom,
                        0,
                        minZoom + 0.05,
                        ['get', 'min_height']
                    ],
                    'fill-extrusion-opacity': 0.9
                }
            };
            return layer;
        }

		function createLabelIcon(text) {
			let popup = document.createElement('div');
			popup.innerHTML = '<span title="' + text + '" style="font-size: 30px;color: yellow;">&#9762;</span>';
			return popup;
		}

		let api = {
			fov: Math.atan(3 / 4) * 180 / Math.PI,
			orthographic: false
		};

		function init() {
			// stats
			stats = new Stats();
			map.getContainer().appendChild(stats.dom);
			animate();
			// gui
			gui = new GUI();
			// going below 2.5 degrees will start to generate serious issues with polygons in fill-extrusions and 3D meshes
			// going above 45 degrees will also produce clipping and performance issues
            gui.add(api, 'fov', 2.5, 45.0).step(0.1).onChange(changeFOV);
            // this will set 0.01 degrees in Mapbox which is the minimum possible and an OrthographicCamera in three.js
			gui.add(api, 'orthographic').name('pure orthographic').onChange(changeFOV);
		}

		function changeFOV() {
			tb.orthographic = api.orthographic;
			tb.fov = api.fov;
		}



    </script>
</body>

